package hell.satan.droidbdf.base;

import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.CallSuper;
import android.support.annotation.Nullable;
import android.support.v4.app.FragmentActivity;

import java.lang.ref.WeakReference;

import hell.satan.droidbdf.survey.SurveyAgent;
import hell.satan.droidbdf.utils.Constants;
import hell.satan.droidbdf.utils.Generator;
import hell.satan.droidbdf.utils.LogWrapper;

/**
 * 所有Activity基类，输出全部生命周期。
 * Super class for all activities, output all lifecycle.
 *
 * @author Cerberus
 */
@SuppressWarnings("unused")
public class BaseActivity extends FragmentActivity implements
        BaseFragment.OnFragmentInteractionListener {
    protected final String TAG = getClass().getSimpleName();

    protected static final Generator GENERATOR = new Generator();

    private boolean mStarted;
    private boolean mResumed;
    private boolean mPaused;
    private boolean mStopped;

    private int mRestarted;

    private ActivityHandler mHandler;

    @CallSuper
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mHandler = new ActivityHandler(this);
        LogWrapper.v(TAG, "onCreate");
        onIntent(getIntent());
    }

    @CallSuper
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        LogWrapper.v(TAG, "onNewIntent");
        onIntent(intent);
    }

    @CallSuper
    @Override
    protected void onStart() {
        super.onStart();
        mStarted = true;
        mStopped = false;
        LogWrapper.v(TAG, "onStart");
    }

    @CallSuper
    @Override
    protected void onResume() {
        super.onResume();
        mResumed = true;
        mPaused = false;
        SurveyAgent.onResume(this);
        LogWrapper.v(TAG, "onResume");
    }

    @CallSuper
    @Override
    protected void onPause() {
        LogWrapper.v(TAG, "onPause");
        SurveyAgent.onPause(this);
        mPaused = true;
        mResumed = false;
        super.onPause();
    }

    @CallSuper
    @Override
    protected void onStop() {
        LogWrapper.v(TAG, "onStop");
        mStopped = true;
        mStarted = false;
        super.onStop();
    }

    @CallSuper
    @Override
    protected void onDestroy() {
        LogWrapper.v(TAG, "onDestroy");
        super.onDestroy();
    }

    @CallSuper
    @Override
    protected void onRestart() {
        super.onRestart();
        mRestarted++;
        LogWrapper.v(TAG, "onRestart");
    }

    /**
     * 当Activity收到Intent时调用此方法。
     * When activity receive an intent.
     *
     * @param intent 收到的Intent。
     *               Intent received.
     * @see #onCreate(Bundle)
     * @see #onNewIntent(Intent)
     */
    @CallSuper
    protected void onIntent(Intent intent) {
        String from = intent.getStringExtra(Constants.EXTRA_ACTIVITY_FROM);
        from = from == null ? "unknown" : from;
        LogWrapper.v(TAG, "from:" + from);
    }

    /**
     * 用于Fragment和Activity的通信交互
     * Communication interaction for Fragment and Activity
     *
     * @see hell.satan.droidbdf.base.BaseFragment.OnFragmentInteractionListener
     */
    @Nullable
    @Override
    public Bundle onFragmentInteraction(BaseFragment fragment, @Nullable Bundle data) {
        return null;
    }

    /**
     * 返回Activity是否已经Start
     * Whether activity is started
     */
    public final boolean getStarted() {
        return mStarted;
    }

    /**
     * 返回Activity是否已经Resumed
     * Whether activity is resumed
     */
    public final boolean getResumed() {
        return mResumed;
    }

    /**
     * 返回Activity是否已经Paused
     * Whether activity is paused
     */
    public final boolean getPaused() {
        return mPaused;
    }

    /**
     * 返回Activity是否已经Stopped
     * Whether activity is stopped
     */
    public final boolean getStopped() {
        return mStopped;
    }

    /**
     * 返回Activity restart的次数
     * Return activity restart times
     */
    public final int getRestarted() {
        return mRestarted;
    }

    /**
     * 在启动Activity的Intent添加来源信息。
     * Add source information to intent when launch an activity.
     *
     * @see android.app.Activity#startActivityForResult(Intent, int, Bundle)
     */
    @Override
    public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        String from = getClass().getCanonicalName();
        Intent target = (Intent) intent.clone();
        target.putExtra(Constants.EXTRA_ACTIVITY_FROM, from);
        super.startActivityForResult(target, requestCode, options);
    }

    /**
     * 在启动Activity的Intent添加来源信息。
     * Add source information to intent when launch activities.
     *
     * @see android.app.Activity#startActivities(Intent[], Bundle)
     */
    @Override
    public void startActivities(Intent[] intents, Bundle options) {
        String from = getClass().getCanonicalName();
        Intent[] targets = new Intent[intents.length];
        for (int i = 0; i < intents.length; i++) {
            targets[i] = (Intent) intents[i].clone();
            targets[i].putExtra(Constants.EXTRA_ACTIVITY_FROM, from);
        }
        super.startActivities(targets, options);
    }

    /**
     * 在启动Service的Intent添加来源信息。
     * Add source information to intent when start service.
     *
     * @see android.app.Activity#startService(Intent)
     */
    @Override
    public ComponentName startService(Intent intent) {
        String from = getClass().getCanonicalName();
        Intent target = (Intent) intent.clone();
        target.putExtra(Constants.EXTRA_ACTIVITY_FROM, from);
        return super.startService(target);
    }

    /**
     * 在绑定Service的Intent添加来源信息。
     * Add source information to intent when bind service.
     *
     * @see android.app.Activity#bindService(Intent, ServiceConnection, int)
     */
    @Override
    public boolean bindService(Intent intent, ServiceConnection conn, int flags) {
        String from = getClass().getCanonicalName();
        Intent target = (Intent) intent.clone();
        target.putExtra(Constants.EXTRA_ACTIVITY_FROM, from);
        return super.bindService(target, conn, flags);
    }

    /**
     * 与{@link android.os.Handler#handleMessage(android.os.Message)}方法功能完全相同，
     * 你可以直接把此Activity当作{@link android.os.Handler}使用，覆盖此方法即可
     * <p/>
     * Same as {@link android.os.Handler#handleMessage(android.os.Message)},
     * you can take this activity as a {@link android.os.Handler}, just need to override this method
     *
     * @see android.os.Handler#handleMessage(android.os.Message)
     */
    @CallSuper
    protected void handleMessage(Message msg) {
    }

    public final boolean sendEmptyMessage(int what) {
        return mHandler.sendEmptyMessage(what);
    }

    public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
        return mHandler.sendEmptyMessageDelayed(what, delayMillis);
    }

    public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
        return mHandler.sendEmptyMessageAtTime(what, uptimeMillis);
    }

    public final boolean sendMessage(Message msg) {
        return mHandler.sendMessage(msg);
    }

    public final boolean sendMessageDelayed(Message msg, long delayMillis) {
        return mHandler.sendMessageDelayed(msg, delayMillis);
    }

    public final boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        return mHandler.sendMessageAtTime(msg, uptimeMillis);
    }

    public final boolean hasMessages(int what) {
        return mHandler.hasMessages(what);
    }

    public final void removeMessages(int what) {
        mHandler.removeMessages(what);
    }

    public final void post(Runnable r) {
        mHandler.post(r);
    }

    public final boolean postDelayed(Runnable run, long delayMillis) {
        return mHandler.postDelayed(run, delayMillis);
    }

    public final boolean postAtTime(Runnable run, Object token, long uptimeMillis) {
        return mHandler.postAtTime(run, token, uptimeMillis);
    }

    public final boolean postAtTime(Runnable run, long uptimeMillis) {
        return mHandler.postAtTime(run, uptimeMillis);
    }

    public final void removeCallbacks(Runnable run) {
        mHandler.removeCallbacks(run);
    }

    private static class ActivityHandler extends Handler {
        private final String TAG;
        private WeakReference<BaseActivity> mActivity;

        public ActivityHandler(BaseActivity activity) {
            TAG = String.format("%1$s$%2$s", activity.getClass().getSimpleName(), getClass().getSimpleName());
            mActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            LogWrapper.v(TAG, msg.toString());
            BaseActivity activity = mActivity.get();
            if (activity != null) {
                activity.handleMessage(msg);
            } else {
                LogWrapper.v(TAG, "Activity has already been recycled, message been abandoned.");
            }
        }
    }
}
